#include <mysql/mysql.h>
#include <stdlib.h>
#include <time.h>
#include <string>
#include <string.h> //for strlen
#include <stdio.h> //for sprintf
#include "md5.h" //Since C++ doesn't have a native MD5 function
#include <sstream>
#include <iostream>

using namespace std;

template <class T>
inline string ToString(const T& t)
{
	stringstream ss;
	ss << t;
	return ss.str();
}

static MYSQL * conn;

void createdb()
{
	mysql_query(conn, "CREATE DATABASE tmp123");
}

void createtable()
{
	mysql_query(conn, "USE tmp123");
	mysql_query(conn, "CREATE TABLE usertest (`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,`username` CHAR(32) NOT NULL,`passwd` CHAR(32) NOT NULL,`email` CHAR(100) NOT NULL,`hash` CHAR(32) NOT NULL,PRIMARY KEY (`id`)  )");
}

void insertrows()
{
	int nRand;
	
	char hex_output[16*2 + 1];
	string data;
	string strpass;
	string hash;
	string idx;
	string sQuery;
	srand ( time(NULL) );
	md5_state_t state;
	md5_byte_t digest[16];
	for (int i = 1; i < 90001; i++)
	{
		md5_init(&state);
		nRand = rand() % (999 - 111 + 1) + 111;
		idx = ToString(i);
		strpass = ToString(nRand);
		data = "example"+idx+strpass+"example"+idx+"@example.com";
		md5_append(&state, (const md5_byte_t *)data.c_str(), strlen(data.c_str()));
		md5_finish(&state, digest);
		for (int di = 0; di < 16; ++di)
			sprintf(hex_output + di * 2, "%02x", digest[di]);
		hash = hex_output;
		sQuery = "INSERT INTO usertest (`id`,`username`,`passwd`,`email`,`hash`) VALUES ( NULL,'example"+idx+"','"+strpass+"','example"+idx+"@example.com','"+hash+"')";
		mysql_query(conn, sQuery.c_str());
	}
}

void selectrows()
{
	md5_state_t state;
	md5_byte_t digest[16];
	char hex_output[16*2 + 1];
	MYSQL_RES * res;
    MYSQL_ROW row;
	string hash;
	string data;
	mysql_query(conn, "SELECT * FROM usertest");
	res = mysql_use_result(conn);

	while ( ( row = mysql_fetch_row(res)) != NULL )
	{
		data = ToString(row[1])+ToString(row[2])+ToString(row[3]);
		md5_init(&state);
		md5_append(&state, (const md5_byte_t *)data.c_str(), strlen(data.c_str()));
		md5_finish(&state, digest);
		for (int di = 0; di < 16; ++di)
			sprintf(hex_output + di * 2, "%02x", digest[di]);
		hash = hex_output;
		if (hash != row[4])
			cout << "Something went wrong!" << endl;
	}

	mysql_free_result(res);
}

void deleterows()
{
	mysql_query(conn, "DELETE FROM usertest");
}

void deletetable()
{
	mysql_query(conn, "DROP TABLE usertest");
}

void deletedb()
{
	mysql_query(conn, "DROP DATABASE tmp123");
}

int main()
{
	conn = mysql_init(NULL);
	mysql_real_connect(conn, "localhost", "root", "root", NULL, 3306, NULL, 0);

	createdb();
	createtable();
	insertrows();
	selectrows();
	deleterows();
	deletetable();
	deletedb();
	
	mysql_close(conn);

	return 0;
}